home *** CD-ROM | disk | FTP | other *** search
- (*---------------------------------------------------------------------------
- :Program. M2ACode
- :Author. Fridtjof Björn Siebert (Amok)
- :Address. Nobileweg 67, D-7000 Stuttgart-40
- :Phone. (0)711/822509
- :Shortcut. [fbs]
- :Version. 0.99
- :Date. 27.03.88
- :Copyright. Intern
- :Language. Modula-II
- :Translator. M2Amiga
- :Imports. none.
- :Contents. Maschinensprache->Modula Converter
- :Bugs. M2Amiga isn't able to convert some Types, such as LONGINT to
- :Bugs. WORD. REG() gives a LONGINT, so a WORD can't be a result.
- ---------------------------------------------------------------------------*)
-
- (*-------------------------------------------------------------------------*)
- (* ----------------- *)
- (* - - - - M 2 A C O D E - - - - - *)
- (* ----------------- *)
- (* *)
- (* Wandelt PC-relative (!) Maschinencodeprogramme in *)
- (* Meier-Vogt M2Amiga Definition- und Implementation-Module um. *)
- (* *)
- (* © 1988 by Fridtjof Siebert *)
- (* Nobileweg 67 *)
- (* 7000 Stuttgart 40 (Stammheim) *)
- (* Germany *)
- (* Phone: (0)711/822509 *)
- (* *)
- (* Usage: *)
- (* M2Code Src {-cRx:Typ|-vRx:Typ|-sRx} [-rRx:Typ] [-sall] [-d] [-e] [-p] *)
- (* (Rx: 68000-Register (D0..D7/A0..A7);) *)
- (* (Typ: Modula-II Type) *)
- (* *)
- (* -cRx: konstanter Parameter wird in Rx übergeben. *)
- (* -vRx: Variabler Parameter in Rx übergeben. *)
- (* -rRx: Ergebnis wird aus Register Rx übergeben. *)
- (* -sRx: Die Rx muß zwischengespeichert werden (bei D2..D7 & A2..A7) *)
- (* -sall: Alle Register zwischenspeichern (außer a7) *)
- (* -d: Letztes Wort löschen, wenn es 0 ist. *)
- (* -e: Entry- & Exit-Code weglassen (Prg muß mit RTS aufhören) *)
- (* -p: Parameterübergabe nicht über Stack, sondern direkt in Regs. *)
- (* *)
- (* Beispiel: *)
- (* M2Code -vA0:ADDRESS -cD0:WORD -rD1:BYTE -sD3 -sD4 *)
- (* erzeugt folgende Procedur: *)
- (* PROCEDURE (VAR a:ADDRESS; b:WORD):BYTE *)
- (* D3 und D4 werden auf den Stack gerettet. *)
- (* *)
- (*-------------------------------------------------------------------------*)
-
- MODULE M2ACode;
-
- (*------ Importlist: ------*)
-
- FROM SYSTEM IMPORT ADR,ADDRESS,BYTE,WORD,BITSET,SHIFT,CAST;
- FROM Arguments IMPORT NumArgs,GetArg;
- FROM Dos IMPORT Open,Close,Read,Write,FileHandlePtr,oldFile,newFile;
- FROM Exec IMPORT AllocMem,FreeMem,MemReqSet,MemReqs;
- FROM InOut IMPORT WriteString,WriteLn;
- FROM Strings IMPORT first,last,Delete,Copy,Insert,Compare,Length,Occurs;
- FROM Conversions IMPORT ValToStr;
-
- (*------ Types: ------*)
-
- TYPE
- String2 = ARRAY[0..2] OF CHAR;
- ArgStr = ARRAY[0..79] OF CHAR;
-
- (*------ Variables: ------*)
-
- VAR
- argc: CARDINAL; (* count args *)
- argv: ARRAY[0..32] OF ArgStr; (* the arguments *)
- ParaCount: CARDINAL; (* Counts Parameters for Procedure *)
- ParaTypes: ARRAY[0..15] OF ARRAY[0..39] OF CHAR; (* the Types *)
- ParaRegs: ARRAY[0..15] OF CARDINAL; (* The Registers for the Parameters *)
- ParaRegStrs: ARRAY[0..15] OF String2; (* The Register's names *)
- ParaVar: ARRAY[0..15] OF BOOLEAN; (* VAR or CONST ? *)
- ResultReg: INTEGER; (* Register for result *)
- ResultType: ARRAY[0..39] OF CHAR; (* Type of result *)
- i,j: INTEGER; (* no special use *)
- CommString: String2; (* the first 2 chars of a argv *)
- RegString: String2; (* the third and fourth char *)
- SaveRegs: BITSET; (* Registers to be saved *)
- LoadRegs: BITSET; (* Registers to be loaded *)
- DoSave: BOOLEAN; (* Save or not ? *)
- DelZero: BOOLEAN; (* Delete last word if it's a zero *)
- NoEntryCode: BOOLEAN; (* Don't create entry & exit code *)
- NoStack: BOOLEAN; (* Don't use stack for Parameters *)
- Char: ARRAY[0..0] OF CHAR; (* for changing a Char to a Array of Chars *)
- SourceFile, ModName, ImplFile, DefFile: ArgStr; (* The Files *)
- InBuffer: POINTER TO CARDINAL; (* Buffer for Input *)
- OutBuffer: POINTER TO ARRAY[0..255] OF CHAR; (* Outputbuffer *)
- InH,OutH: FileHandlePtr; (* FileHandles for I/O *)
- len: LONGCARD; (* for saving Writes's result *)
- RegNumString: ARRAY[0..39] OF CHAR; (* the Converted Register-Number *)
- Hex: ARRAY[0..39] OF CHAR; (* for Hex-Numbers *)
- ok,ok2: BOOLEAN; (* for getting boolean results *)
- code: CARDINAL; (* for saving read machinecode *)
-
- (*------ Convert Registerstring (D0,a5 etc) into number (0..15) : -------*)
-
- PROCEDURE CalcReg(RegStr: String2): CARDINAL;
-
- VAR
- Reg: CARDINAL;
-
- BEGIN
- IF (RegStr[0]="d") OR (RegStr[0]="D") THEN Reg := 0;
- ELSIF (RegStr[0]="a") OR (RegStr[0]="A") THEN Reg := 8;
- ELSE WriteString("Unknown Register"); WriteLn(); HALT; END;
- Reg := Reg + CARDINAL(ORD(RegStr[1]) - ORD("0"));
- IF Reg>15 THEN WriteString("Unknown Register"); WriteLn(); HALT; END;
- RETURN Reg;
- END CalcReg;
-
- (*--------------------- String ausgeben: --------------------------------*)
-
- PROCEDURE WriteBuf(Lines:CARDINAL);
-
- BEGIN
- IF Write(OutH,OutBuffer,LONGCARD(Length(OutBuffer^)))= -1 THEN
- Close(OutH);
- IF InH#NIL THEN Close(InH) END;
- WriteString("Error while writing"); WriteLn; HALT;
- END;
- OutBuffer^[0] := CHR(10); len := Write(OutH,OutBuffer,1);
- WHILE Lines>1 DO
- len := Write(OutH,OutBuffer,1); DEC(Lines);
- END;
- END WriteBuf;
-
- (*------------------- LineFeed ausgeben: --------------------------------*)
-
- PROCEDURE LF(Lines: CARDINAL);
-
- BEGIN
- OutBuffer^[0] := CHR(10); len := Write(OutH,OutBuffer,1);
- WHILE Lines>1 DO
- len := Write(OutH,OutBuffer,1); DEC(Lines);
- END;
- END LF;
-
- (*------------------------- Start ---------------------------------------*)
-
- BEGIN
-
- (*------ Get Commandline: ------*)
-
- argc := NumArgs();
- IF argc>33 THEN WriteString("Too many parameters"); WriteLn(); HALT; END;
-
- (*------ No Parameters? Then type Usage: ------*)
-
- IF argc=0 THEN
- WriteString("Usage:"); WriteLn;
- WriteString("M2Code [-cRx:Type] [-vRx:Type] [-rRx:Type] [-sRx] [-sall] [-d]"); WriteLn;
- WriteString(" (Rx: 68000-Register (d0..a7), Type: Modula TYPE-name)");WriteLn;
- WriteLn;
- WriteString(" -c : constant Parameter"); WriteLn;
- WriteString(" -v : variable Parameter"); WriteLn;
- WriteString(" -r : Result"); WriteLn;
- WriteString(" -s : save Register "); WriteLn;
- WriteString(" -sall : save all Registers (apart from a7)"); WriteLn;
- WriteString(" -d : delete last 2 Bytes from Source, if they are zeroes"); WriteLn;
- WriteString(" -e : no entry and exit-code for the procedure"); WriteLn;
- WriteString(" -p : put parameters directly into regs, don't use Stack"); WriteLn;
- WriteString(" This utility was written for Meier-Vogt M2Amiga."); WriteLn;
- WriteString(" © 1988 by Fridtjof Siebert, Nobileweg 67,D-7000 Stgt-40"); WriteLn;
- WriteString(" Phone: (0)711/822509"); WriteLn;
- HALT;
- ELSE
-
- (*------ read parameters ------*)
-
- FOR i:=1 TO argc DO
- GetArg(i,argv[i-1],j);
- END;
-
- END;
-
- (*------ create Filename: ------*)
-
- SourceFile := argv[0];
- i:= Occurs(SourceFile,first,".",TRUE);
- IF i#last THEN
- Copy(ModName,SourceFile,0,i); (* Delete Suffix *)
- ELSE
- ModName := SourceFile;
- END;
- ImplFile := ModName; Insert(ImplFile,last,".mod");(* add .mod for Impl. *)
- DefFile := ModName; Insert(DefFile ,last,".def"); (* add .def for Def. *)
-
- (*------ analyse rest of commandline: ------*)
-
- (* Default Settings: *)
- DoSave := FALSE; SaveRegs := {}; LoadRegs := {}; ResultReg := -1;
- DelZero := FALSE; NoEntryCode := FALSE; NoStack := FALSE;
-
- ParaCount := 0; i := 1; (* init loop *)
- WHILE CARDINAL(i)<argc DO
- Copy (CommString,argv[i],0,2); (* `-x' nach CommString *)
- Copy (RegString ,argv[i],2,2); (* `Rx' nach RegString *)
- IF Compare(argv[i],first,5,"-sall",FALSE)=0 THEN (* alle Regs speichern *)
- SaveRegs := {1..15}; LoadRegs := {0..14}; DoSave:= TRUE;
- ELSIF Compare(CommString,first,2,"-s",FALSE)=0 THEN (* ein Reg speichern: *)
- INCL(SaveRegs,15-CalcReg(RegString));
- INCL(LoadRegs, CalcReg(RegString));
- DoSave := TRUE;
- ELSIF Compare(CommString,first,2,"-d",TRUE)=0 THEN (* Nullwort löschen *)
- DelZero := TRUE;
- ELSIF Compare(CommString,first,2,"-e",TRUE)=0 THEN (* no Entry&Exit Code *)
- NoEntryCode := TRUE;
- ELSIF Compare(CommString,first,2,"-r",TRUE)=0 THEN (* Result in Rx *)
- ResultReg := CalcReg(RegString);
- Copy(ResultType,argv[i],4,Length(argv[i])-4);
- ELSIF Compare(CommString,first,2,"-p",TRUE)=0 THEN (* Don't use Stack *)
- NoStack := TRUE;
- ELSE
- IF Compare(CommString,first,2,"-c",TRUE)=0 THEN (* Konstante übergeben: *)
- ParaRegs[ParaCount] := CalcReg(RegString);
- ParaRegStrs[ParaCount] := RegString; ParaVar[ParaCount] := FALSE;
- Copy(ParaTypes[ParaCount],argv[i],4,Length(argv[i])-4);
- ELSIF Compare(CommString,first,2,"-v",TRUE)=0 THEN (* Variable übergeben: *)
- ParaRegs[ParaCount] := CalcReg(RegString);
- ParaRegStrs[ParaCount] := RegString; ParaVar[ParaCount] := TRUE;
- Copy(ParaTypes[ParaCount],argv[i],4,Length(argv[i])-4);
- ELSE (* unkorrekter Parameter: *)
- WriteString("Unknown Parameter"); WriteLn(); HALT;
- END;
- INC(ParaCount); (* increament number of Parameters *)
- IF ParaCount=17 THEN WriteString("Too Many Parameters"); WriteLn; HALT; END;
- END;
- INC(i);
- END;
-
- InBuffer := AllocMem(272,MemReqSet{chip,memClear}); (* Speicher *)
- OutBuffer := ADDRESS(LONGCARD(InBuffer) + 16);
-
- (*------ Definition Module erzeugen: ------*)
-
- OutH := Open(ADR(DefFile),newFile); (* Open defmodule for writing *)
- IF OutH=NIL THEN WriteString("Couldn't open "); WriteString(DefFile); WriteLn; HALT; END;
-
- WriteLn; WriteString("Creating Definition Module: "); WriteString(DefFile);
- WriteLn; WriteLn; InH := NIL;
-
- (*------ First Line: ------*)
-
- OutBuffer^ := "DEFINITION MODULE "; Insert(OutBuffer^,last,ModName);
- Insert(OutBuffer^,last,";"); WriteBuf(2);
-
- (*------ ImportList: ------*)
-
- OutBuffer^ := "FROM SYSTEM IMPORT BYTE,WORD,ADDRESS,BITSET,LONGSET,FFP;";
- WriteBuf(2);
-
- (*------ The Procedure: ------*)
-
- OutBuffer^ := "(*------ "; Insert(OutBuffer^,last,ModName);
- Insert(OutBuffer^,last," ------*)"); WriteBuf(2);
-
- OutBuffer^ := "PROCEDURE ";Insert(OutBuffer^,last,ModName);
- Insert(OutBuffer^,last,"("); i := 0;
-
- (*------ create Parameterlist: ------*)
-
- WHILE CARDINAL(i)<ParaCount DO
- IF ParaVar[i] THEN Insert(OutBuffer^,last,"VAR ") END;
- IF NoStack THEN (* parameters directly into Registers *)
- Insert(OutBuffer^,last,ParaRegStrs[i]); Insert(OutBuffer^,last,"{");
- ValToStr(LONGCARD(ParaRegs[i]),FALSE,Hex,10,2," ",ok);
- Insert(OutBuffer^,last,Hex); Insert(OutBuffer^,last,"}");
- ELSE
- Char[0]:= CHR(i+97); Insert(OutBuffer^,last,Char);
- END;
- Insert(OutBuffer^,last,ParaTypes[i]); INC(i);
- IF CARDINAL(i)<ParaCount THEN Insert(OutBuffer^,last,";"); END;
- END;
- Insert(OutBuffer^,last,")");
- IF ResultReg#-1 THEN Insert(OutBuffer^,last,ResultType) END;
- Insert(OutBuffer^,last,";"); WriteBuf(2);
-
- (*------ The End: ------*)
-
- OutBuffer^ := "END "; Insert(OutBuffer^,last,ModName);
- Insert(OutBuffer^,last,"."); WriteBuf(1);
-
- Close(OutH); (* Definition Module ready *)
-
- (*------ Implementation Module erzeugen: ------*)
-
- InH := Open(ADR(SourceFile),oldFile); (* open source for reading *)
- IF InH=NIL THEN WriteString(SourceFile); WriteString(" not found."); WriteLn; HALT END;
-
- WriteString("Source File: "); WriteString(SourceFile); WriteLn; WriteLn;
-
- OutH := Open(ADR(ImplFile),newFile); (* open ImplModule for writing *)
- IF OutH=NIL THEN Close(InH); WriteString("Couldn't open "); WriteString(ImplFile); WriteLn; HALT; END;
-
- WriteString("Creating Implementation Module: "); WriteString(ImplFile);
- WriteLn; WriteLn;
-
- (*------ First Line: ------*)
-
- OutBuffer^ := "IMPLEMENTATION MODULE "; Insert(OutBuffer^,last,ModName);
- Insert(OutBuffer^,last,";"); WriteBuf(2);
-
- (*------ Entry and Exit code: ------*)
-
- IF NoEntryCode THEN OutBuffer^ := "(*$E-*)"; WriteBuf(2) END;
-
- (*------ Importlist: ------*)
-
- OutBuffer^ := "FROM SYSTEM IMPORT BYTE,WORD,ADDRESS,BITSET,LONGSET,FFP,INLINE,SETREG,REG;";
- WriteBuf(2);
-
- (*------ Constants for saving registers: ------*)
-
- IF DoSave THEN
- OutBuffer^ := "CONST"; WriteBuf(1);
- OutBuffer^ := " MOVEMS = 48E7H;"; WriteBuf(1);
- OutBuffer^ := " MOVEML = 4CDFH;"; WriteBuf(2);
- END;
-
- (*------ The Procedure: ------*)
-
- OutBuffer^ := "(*------ "; Insert(OutBuffer^,last,ModName);
- Insert(OutBuffer^,last," ------*)"); WriteBuf(2);
-
- OutBuffer^ := "PROCEDURE "; Insert(OutBuffer^,last,ModName);
- Insert(OutBuffer^,last,"("); i := 0;
-
- (*------ Create Parameterlist: ------*)
-
- WHILE CARDINAL(i)<ParaCount DO
- IF ParaVar[i] THEN Insert(OutBuffer^,last,"VAR ") END;
- IF NoStack THEN (* parameters directly into Registers *)
- Insert(OutBuffer^,last,ParaRegStrs[i]); Insert(OutBuffer^,last,"{");
- ValToStr(LONGCARD(ParaRegs[i]),FALSE,Hex,10,2," ",ok);
- Insert(OutBuffer^,last,Hex); Insert(OutBuffer^,last,"}");
- ELSE
- Char[0]:= CHR(i+97); Insert(OutBuffer^,last,Char);
- END;
- Insert(OutBuffer^,last,ParaTypes[i]); INC(i);
- IF CARDINAL(i)<ParaCount THEN Insert(OutBuffer^,last,";"); END;
- END;
- Insert(OutBuffer^,last,")");
- IF ResultReg#-1 THEN Insert(OutBuffer^,last,ResultType) END;
- Insert(OutBuffer^,last,";"); WriteBuf(2);
-
- (*------ begin: ------*)
-
- OutBuffer^ := "BEGIN"; WriteBuf(2);
-
- (*------ Save Registers: ------*)
-
- IF DoSave THEN
- OutBuffer^ := " INLINE(MOVEMS,";
- ValToStr(LONGCARD(CAST(CARDINAL,SaveRegs)),FALSE,Hex,16,5,"0",ok);
- Insert(OutBuffer^,last,Hex); Insert(OutBuffer^,last,"H);");
- WriteBuf(2);
- END;
-
- (*------ Put parameters into Registers: ------*)
-
- IF NOT(NoStack) THEN
- i := 0;
- WHILE CARDINAL(i)<ParaCount DO
- OutBuffer^ := " SETREG(";
- ValToStr(LONGCARD(ParaRegs[i]),FALSE,RegNumString,10,2," ",ok);
- Insert(OutBuffer^,last,RegNumString);
- Insert(OutBuffer^,last,",ADDRESS(");
- Char[0] := CHR(i+97); Insert(OutBuffer^,last,Char);
- Insert(OutBuffer^,last,"));"); WriteBuf(1); INC(i);
- END;
- LF(1);
- END;
-
- (*------ insert Machine-Code: ------*)
-
- len := Read(InH,InBuffer,2); code := InBuffer^;
- OutBuffer^ := " INLINE("; i := 0;
-
- WHILE Read(InH,InBuffer,2)=2 DO
- ValToStr(LONGCARD(code),FALSE,Hex,16,5,"0",ok);
- Insert(OutBuffer^,last,Hex); Insert(OutBuffer^,last,"H");
- INC(i);
- IF i=8 THEN
- Insert(OutBuffer^,last,");"); WriteBuf(1);
- i := 0; OutBuffer^ := " INLINE(";
- ELSE
- Insert(OutBuffer^,last,",");
- END;
- code := InBuffer^;
- END;
- IF DelZero AND (code=0) AND NOT(ODD(SHIFT(i,1))) THEN (* del Zero *)
- IF i#0 THEN
- Delete(OutBuffer^,Length(OutBuffer^)-1,1);
- Insert(OutBuffer^,last,");");
- WriteBuf(1);
- END;
- ELSE
- ValToStr(LONGCARD(code),FALSE,Hex,16,5,"0",ok);
- Insert(OutBuffer^,last,Hex); Insert(OutBuffer^,last,"H);");
- WriteBuf(1);
- END;
- LF(1);
-
- (*------ get Variable parameters from Registers: ------*)
-
- IF NOT(NoStack) THEN
- i := 0;
- WHILE CARDINAL(i)<ParaCount DO
- IF ParaVar[i] THEN
- Char[0] := CHR(i+97);
- OutBuffer^ := " "; Insert(OutBuffer^,last,Char);
- Insert(OutBuffer^,last," := ");
- Copy(Hex,ParaTypes[i],1,Length(ParaTypes[i])-1); (* delete `:' *)
- Insert(OutBuffer^,last,Hex);
- Insert(OutBuffer^,last,"(REG(");
- ValToStr(LONGCARD(ParaRegs[i]),FALSE,RegNumString,10,2," ",ok);
- Insert(OutBuffer^,last,RegNumString);
- Insert(OutBuffer^,last,"));"); WriteBuf(1);
- END;
- INC(i);
- END;
- IF ParaCount#0 THEN LF(1) END;
- END;
-
- (*------ Return the Result: ------*)
-
- IF ResultReg#-1 THEN
- OutBuffer^ := " RETURN "; Insert(OutBuffer^,last,ResultType);
- Delete(OutBuffer^,9,1); Insert(OutBuffer^,last,"(REG(");
- ValToStr(LONGCARD(ResultReg),FALSE,RegNumString,10,2," ",ok);
- Insert(OutBuffer^,last,RegNumString); Insert(OutBuffer^,last,"));");
- WriteBuf(2);
- END;
-
- (*------ get saved Registers back: ------*)
-
- IF DoSave THEN
- OutBuffer^ := " INLINE(MOVEML,";
- ValToStr(LONGCARD(CAST(CARDINAL,LoadRegs)),FALSE,Hex,16,5,"0",ok);
- Insert(Hex,0,"0000"); Delete(Hex,0,Length(Hex)-5);
- Insert(OutBuffer^,last,Hex); Insert(OutBuffer^,last,"H);");
- WriteBuf(2);
- END;
-
- (*------ The End: ------*)
-
- OutBuffer^ := "END "; Insert(OutBuffer^,last,ModName);
- Insert(OutBuffer^,last,";"); WriteBuf(2);
-
- (*------ Initialisation: (empty) ------*)
-
- OutBuffer^ := "BEGIN"; WriteBuf(1);
-
- OutBuffer^ := "END "; Insert(OutBuffer^,last,ModName);
- Insert(OutBuffer^,last,"."); WriteBuf(1);
-
- (*------ Close Files: ------*)
-
- Close(OutH);
- Close(InH);
-
- (*------ Get Mem back: ------*)
-
- FreeMem(InBuffer,272);
-
- (*------ That's it! ------*)
-
- END M2ACode.
-
- (*-------------------------------------------------------------------------*)
- (* *)
- (* Thanks to the flu I had the week I wrote this. Whithout it I would *)
- (* have had to go to school and write 3 (!!!) tests. There wouldn't *)
- (* have been any time for me to write a programme. Now this is working *)
- (* and my flu is gone! Here comes the weekend! *)
- (* *)
- (*-------------------------------------------------------------------------*)
-